package com.easy.project.service.builder.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import com.easy.project.base.domain.po.BasePO;
import com.easy.project.config.BaseConfig;
import com.easy.project.domain.dto.builder.BuilderDTO;
import com.easy.project.domain.dto.builder.DataSourceDTO;
import com.easy.project.domain.vo.builder.SelectTableVO;
import com.easy.project.service.builder.IBuilderCodeService;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author wxz
 */
@Service
public class BuilderCodeServiceImpl implements IBuilderCodeService {

    @Resource
    private BaseConfig baseConfig;

    private static final String PROJECT_PATH = System.getProperty("user.dir") + "/src/main";

    private static final String JAVA_PATH = PROJECT_PATH + "/java";

    private static final String RESOURCES_PATH = PROJECT_PATH + "/resources";

    private static final String MAPPER_PATH = RESOURCES_PATH + "/mapper/";

    @Override
    public void builder(BuilderDTO builderDTO) {
        FastAutoGenerator.create(dataSourceConfigBuilder(builderDTO))
                .globalConfig(builder -> {
                    // 全部配置
                    globalConfigBuilder(builder, builderDTO);
                })
                .packageConfig(builder -> {
                    packageConfigBuilder(builder, builderDTO);
                })
                .strategyConfig(builder -> {
                    strategyConfigBuilder(builder, builderDTO);
                })
                // 模板引擎选择
                .templateEngine(new FreemarkerTemplateEngine())
                .execute();
    }

    @Override
    public List<SelectTableVO> tableNames(DataSourceDTO dataSourceDTO) {
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(hikariDataSourceBuilder(dataSourceDTO));
        List<String> tables =jdbcTemplate.queryForList("SHOW TABLES",String.class);
        if (CollectionUtil.isEmpty(tables)){
            return Collections.emptyList();
        }
        return toSelectTableVOList(tables);
    }


    private List<SelectTableVO> toSelectTableVOList(List<String> tables){
        List<SelectTableVO> selectTableVOList = new ArrayList<>();
        for (String table : tables){
            SelectTableVO selectTableVO = new SelectTableVO();
            selectTableVO.setName(table);
            selectTableVO.setValue(table);
            selectTableVOList.add(selectTableVO);
        }
        return selectTableVOList;
    }

    private HikariDataSource hikariDataSourceBuilder(DataSourceDTO dataSourceDTO){
        HikariDataSource hikariDataSource = new HikariDataSource();
        hikariDataSource.setJdbcUrl(dataSourceDTO.getUrl());
        hikariDataSource.setUsername(dataSourceDTO.getUserName());
        hikariDataSource.setPassword(dataSourceDTO.getPassword());
        hikariDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        return hikariDataSource;
    }

    /**
     * 数据源创建
     *
     * @return
     */
    private DataSourceConfig.Builder dataSourceConfigBuilder(BuilderDTO builderDTO) {
        return new DataSourceConfig.Builder(builderDTO.getUrl(), builderDTO.getUserName(), builderDTO.getPassword());
    }

    /**
     * 全局配置
     */
    private void globalConfigBuilder(GlobalConfig.Builder builder, BuilderDTO builderDTO) {
        builder.author(builderDTO.getAuthor())
                // 默认开启swagger模式
                .enableSwagger();
        if (builderDTO.isCodeInProject()){
            builder.outputDir(JAVA_PATH);
        }else {
            builder.outputDir(builderDTO.getCodePath());
        }
    }

    /**
     * 包配置
     *
     * @param builder
     * @param builderDTO
     */
    private void packageConfigBuilder(PackageConfig.Builder builder, BuilderDTO builderDTO) {
        builder.parent(baseConfig.getBasePackage())
                .controller("controller." + builderDTO.getModuleName())
                .entity("domain.po." + builderDTO.getModuleName())
                .service("service." + builderDTO.getModuleName())
                .serviceImpl("service." + builderDTO.getModuleName() + ".impl")
                .mapper("mapper." + builderDTO.getModuleName());
        // 设置xml的路径
        if (builderDTO.isCodeInProject()) {
            builder.pathInfo(Collections.singletonMap(OutputFile.xml, MAPPER_PATH + builderDTO.getModuleName()));
        }else {
            // 指定文件路径
            builder.pathInfo(Collections.singletonMap(OutputFile.xml, builderDTO.getCodePath() + "\\" + baseConfig.getBasePackage().replace(".","\\") + "\\resources\\"));

        }

    }

    /**
     * 策略配置
     *
     * @param builder
     * @param builderDTO
     */
    private void strategyConfigBuilder(StrategyConfig.Builder builder, BuilderDTO builderDTO) {
        // 匹配表的名称
        builder.addInclude(builderDTO.getTableNames());
        // 实体类配置
        builder.entityBuilder()
                .superClass(BasePO.class)
                .enableLombok()
                .formatFileName("%sPO")
                .enableTableFieldAnnotation();
        // controller配置
        builder.controllerBuilder()
                .enableHyphenStyle()
                .enableRestStyle();
    }


}
